package com.yang.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static com.yang.constants.RabbitMqConstants.*;
/**
 * <p>
 * 消息配置类
 * </p>
 * @author yang
 * @date 2023/6/25
 */
@Configuration
public class RabbitMqConfig {
//    /**
//     * 消息转换器
//     */
//    @Bean
//    public MessageConverter messageConverter() {
//        return new Jackson2JsonMessageConverter();
//    }

    /**
     * 线程工厂，防止mq消息堆积
     */
    @Bean("customContainerFactory")
    public SimpleRabbitListenerContainerFactory containerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        //设置线程数
        factory.setConcurrentConsumers(10);
        //最大线程数
        factory.setMaxConcurrentConsumers(10);
        configurer.configure(factory, connectionFactory);
        return factory;
    }

    /**
     *  订单队列
     */
    @Bean
    public Queue orderQueue() {
        return new Queue(ORDER_QUEUE, true);
    }

    /**
     * 订单交换机
     */
    @Bean
    public DirectExchange orderExchange() {
        return new DirectExchange(ORDER_EXCHANGE, true, false);
    }

    /**
     * 队列通过路由键绑定到交换机
     */
    @Bean
    public Binding orderBind() {
        return BindingBuilder.bind(orderQueue()).to(orderExchange()).with(ORDER_ROUTING_KEY);
    }

    /**
     * 本地消息表队列
     */
    @Bean
    public Queue messageQueue(){
        return new Queue(MESSAGE_QUEUE, true,false,false);
    }

    /**
     * 本地消息表交换机
     */
    @Bean
    public TopicExchange messageExchange() {
        return new TopicExchange(MESSAGE_EXCHANGE, true, false);
    }

    /**
     * 本地消息表队列绑定本地消息表交换机
     */
    @Bean
    public Binding messageBind() {
        return BindingBuilder.bind(messageQueue()).to(messageExchange()).with(MESSAGE_ROUTING_KEY);
    }

    /**
     * 消息确认回调函数
     *
     * 推送消息存在四种情况：
     * 1.消息推送到sever，交换机和队列啥都没找到
     * 2.消息推送到server，但是在server里找不到交换机
     * 3.消息推送到server，找到交换机了，但是没找到队列
     * 4.消息推送成功
     *
     * 情况 1/2/4 会进入 confirm 回调函数
     * 情况3两个回调函数都会进入
     */
    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);
        // 设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
        rabbitTemplate.setMandatory(true);

        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            System.out.println("ConfirmCallback:     "+"相关数据："+correlationData);
            System.out.println("ConfirmCallback:     "+"确认情况："+ack);
            System.out.println("ConfirmCallback:     "+"原因："+cause);
        });

        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            System.out.println("ReturnCallback:     "+"消息："+message);
            System.out.println("ReturnCallback:     "+"回应码："+replyCode);
            System.out.println("ReturnCallback:     "+"回应信息："+replyText);
            System.out.println("ReturnCallback:     "+"交换机："+exchange);
            System.out.println("ReturnCallback:     "+"路由键："+routingKey);
        });

        return rabbitTemplate;
    }
}
